#include<iostream>
#include<unistd.h>//调用系统接口，只能用c的头文件
#include<stdlib.h>
#include<string>
#include<cstdio>
#include<sys/types.h>
#include<sys/wait.h>
#include<cstring>
using namespace std;

#define N 2

//写
void Writer(int wfd)
{
    string s="hello,i am child";
    pid_t self=getpid();
    int number=0;

    char buffer[1024];
    //用户级缓冲区
    while(true)
    {
        //构建发送字符串
        buffer[0]=0;//字符串清空，只是为了提醒阅读代码的人，我把这个数组当字符串了
        //sprintf(char *str,格式化)即从打印到屏幕上改到打印到缓冲区str中
        snprintf(buffer,sizeof(buffer),"%s-%d-%d",s.c_str(),self,number++);
        //c语言风格函数，输入buffer后会自动加0

        //cout<<buffer<<endl;

        //发送/写入给父进程
        write(wfd,buffer,strlen(buffer));//strlen不用加1，系统调用只要字符串内容
                                        //不需要c语言的分隔符\0
        //通过系统接口访问管道

        sleep(1);
    }
}
//读
void Reader(int rfd)
{
    char buffer[1024];
    while(true)
    {
        buffer[0]=0;
        ssize_t n=read(rfd,buffer,sizeof(buffer));//sizeof是整个数组
        //从文件缓冲区拷贝到用户级缓冲区
        if(n>0)
        {
            buffer[n]=0;//0=='\0'
            cout<<"father get a message"<<getpid()<<"]#"<<buffer<<endl;
        }
    }
}

int main()
{
    int pipefd[N]={0};
    int n=pipe(pipefd);
    if(n<0)return 1;

    //cout<<"pipefd[0]:"<<pipefd[0]<<",pipefd[1]:"<<pipefd[1]<<endl;

    //让子进程写入，父进程读取
    pid_t id=fork();
    if(id<0)return 2;
    if(id==0)
    {
        //child
        close(pipefd[0]);
        //开始通信
        Writer(pipefd[1]);


        close(pipefd[1]);
        exit(0);
    }
    else
    {
        //father
        close(pipefd[1]);
        Reader(pipefd[0]);

        pid_t rid=waitpid(id,nullptr,0);
        if(rid<0)return 3;

        close(pipefd[0]);
    }
    return 0;
}